<?php


namespace app\tcpserver\controller;

use app\admin\model\AlarmLog;
use app\admin\model\AlarmRules;
use app\admin\model\Device;
use app\admin\model\HistoryData;
use think\Exception;
use think\worker\Server;
use Workerman\Lib\Timer;
use think\cache\driver\Redis;

class TimertwoServer extends Server
{
    public function predis()
    {
        return new Redis([
            'host' => '127.0.0.1',
            'port' => 6379,
            'password' => 'xiaochun123',
            'select' => 0,
            'timeout' => 0,
            'expire' => 0,
            'persistent' => false,
            'prefix' => '',
            'serialize' => true,
        ]);
    }

    public function onWorkerStart($worker)
    {
        date_default_timezone_set('PRC');

        $model = new HistoryData();
        $redis = $this->predis();

        // 每40s入库一次
        Timer::add(10, function () use ($redis, $worker, $model) {

            // 获取设备列表
            $devices = Device::where('mark',1)->where('id','>=',46)->select();

            foreach ($devices as $device){
                $tao = $device['device_no'];//默认第一套
                $device_id = $device['id'];
                $data = $this->popMultiFromRedisList('heartLogsOfDevice' . $tao, 5);
//                var_dump($data);
                if(count($data) == 5){
                    $saveData = [
                        'device_no' => '设备device_no',
                        'create_user' => 1,
                        'create_time' => time(),
                        'blHigh' => 0,
                        'blLow' => 0,
                        'bkll' => 0,
                        'gkll' => 0,
                        'wd' => 0,
                        'yl' => 0,
                        'yali'=>0,
                        'temp'=>0,
                        'pinlv'=>0,
                        'voltage'=>0,
                        'run_power'=>0,
                        'run_speed'=>0,
                        'mother_voltage'=>0,
                        'run_len'=>0,
                        'tao_value'=>0,
                        'dianliu'=>0,
                        // 以下值来自设备
                        'chanshui'=>isset($device['chanshui']) ? $device['chanshui'] : 0, //产水
                        'xiangdui_high'=>isset($device['xiangdui_high']) ? $device['xiangdui_high'] : 0, //相对高差
                        'chuandongbi'=>isset($device['chuandongbi']) ? $device['chuandongbi'] : 0, //传动比
                    ];

                    foreach ($data as $item) {
                        // json => arr
                        $arr = json_decode($item,true);
                        $type = $arr['type'];
                        switch ($type) {
                            // 气表
                            case 1:
                                $saveData["blHigh"] = isset($arr["blHigh"]) ? $arr["blHigh"] : 0; //标况总量高位
                                $saveData["blLow"] = isset($arr["blLow"]) ? $arr["blLow"] : 0;  //标况总量低位
                                $saveData["bkll"] = isset($arr["bkll"]) ? $arr["bkll"] : 0;//标况流量 即瞬时气量
                                $saveData["gkll"] = isset($arr["gkll"]) ? $arr["gkll"] : 0; //工况流量
                                $saveData["wd"] = isset($arr["wd"]) ? $arr["wd"] : 0; //流量计温度    单位：℃
                                $saveData["yl"] = isset($arr["yl"]) ? $arr["yl"] : 0; //流量计压力
                                $saveData['device_no'] = $arr["uni_name"]; // 设备编号

                                $this->alarmConditions($arr["times"],'shunshi_qiliang',$saveData["bkll"],$device_id);
                                $this->alarmConditions($arr["times"],'liuliang_temp',$saveData["wd"],$device_id);
                                $this->alarmConditions($arr["times"],'liuliang_yali',$saveData["yl"],$device_id);

                                break;
                            // 井下压力计
                            case 2:
                                $saveData["yali"] = isset($arr["yali"]) ? $arr["yali"] : 0; //流压 单位 MPa
                                $saveData["temp"] = isset($arr["temp"]) ? $arr["temp"] : 0; //井底温度 单位：℃
                                $saveData['device_no'] = $arr["uni_name"]; // 设备编号

                                $this->alarmConditions($arr["times"],'liuya',$saveData["yali"],$device_id);
                                $this->alarmConditions($arr["times"],'jingdi_temp',$saveData["temp"],$device_id);

                                break;
                            // 变频器
                            case 3:
                                $saveData["pinlv"] = isset($arr["pinlv"]) ? $arr["pinlv"] : 0; //运行频率
                                $saveData["voltage"] = isset($arr["voltage"]) ? $arr["voltage"] : 0; //运行电压  V
                                $saveData["run_power"] = isset($arr["run_power"]) ? $arr["run_power"] : 0;//运行功率  w
                                $saveData["run_speed"] = isset($arr["run_speed"]) ? $arr["run_speed"] : 0; //运行速度
                                $saveData["mother_voltage"] = isset($arr["mother_voltage"]) ? $arr["mother_voltage"] : 0; //母线电压 v
                                $saveData["run_len"] = isset($arr["run_len"]) ? $arr["run_len"] : 0; //运行转矩
                                $saveData['device_no'] = $arr["uni_name"]; // 设备编号
                                if (isset($arr["current"])){
                                    $saveData['dianliu'] = $arr["current"]; // 电流
                                }

                                $this->alarmConditions($arr["times"],'pinlv',$saveData["pinlv"],$device_id);
                                $this->alarmConditions($arr["times"],'dianya',$saveData["voltage"],$device_id);
                                break;
                            // 套压压力计
                            case 4:
                                $saveData["tao_value"] = isset($arr["tao_value"]) ? $arr["tao_value"] : 0; //套压值 单位 MPa
                                $saveData['device_no'] = $arr["uni_name"]; // 设备编号

                                $this->alarmConditions($arr["times"],'taoya',$saveData["tao_value"],$device_id);
                                break;
                            // 电流
                            case 5:
                                $saveData["dianliu"] = isset($arr["current"]) ? $arr["current"] : 0; //电流 单位 A
                                $saveData['device_no'] = $arr["uni_name"]; // 设备编号

                                $this->alarmConditions($arr["times"],'dianliu',$saveData["dianliu"],$device_id);
                                break;
                        }
                    }

//                    var_dump($saveData);

                    //  液柱高度：为计算量（流压-套压）*0.98*1000
                    //  校准流压：为计算量（流压+相对高差（开放口，根据现场数据自行添加））
                    //  展示页面转速改为转速（RPM）/冲次(次/分)：为计算量（频率*传动比（开放口，根据现场数据自行添加））

                    $saveData['yezhu_high'] = ((int)$saveData["yali"] - (int)$saveData["tao_value"]) * 0.98 * 1000;
                    $saveData['biao_liuya'] = (int)$saveData["yali"] + (int)$device['xiangdui_high'];

                    try{
                        $this->alarmConditions($arr["times"],'yezhu_high',$saveData['yezhu_high'],$device_id);
                        $this->alarmConditions($arr["times"],'biao_liuya',$saveData['biao_liuya'],$device_id);
                    }catch (Exception $e){
                        echo $e->getMessage().$e->getFile().$e->getLine();
                    }

                    $res = $model->insert($saveData);

                    if($res){
//                        echo 'insert success!'.PHP_EOL;
                    }
                }
            }
        });
    }

    // 从 Redis 的 key 列表中一次性 pop 多条数据
    public function popMultiFromRedisList(string $key, int $count)
    {
        $result = [];
        // 大于$count条数据时再获取数据
        if($this->predis()->llen($key) >= $count){
            for ($i = 0; $i < $count; $i++) {
                $result[] = $this->predis()->rpop($key);
//                var_dump($result);
            }
        }
        return $result;
    }

    // 判断是否满足报警条件
    public function alarmConditions($currentTime,$param,$value,$device_id)
    {
        // 报警规则
        $alarmRules = AlarmRules::where(['param'=>$param,'device_id'=>$device_id,'status'=>1,'mark'=>1])->order('alarm_level desc')->select();
        $deviceId = $device_id;
        $fieldValue = $value;

        // 进行数据筛选、存储
        foreach ($alarmRules as $rule) {
            $parameter = $rule['param'];
            $condition = $rule['relationship'];
            $maxValue = isset($rule['threshold_end']) ? $rule['threshold_end'] : null;
            $minValue = isset($rule['threshold_start']) ? $rule['threshold_start'] : null;
            $alarmLevel = $rule['alarm_level'];

            // 判断是否符合报警条件
            switch ($condition) {
                case '>':
                    if ($fieldValue > $minValue) {
                        $this->saveAlarmRecord($currentTime, $parameter, $fieldValue, $alarmLevel, $deviceId);
                    }
                    break;
                case '<':
                    if ($fieldValue < $minValue) {
                        $this->saveAlarmRecord($currentTime, $parameter, $fieldValue, $alarmLevel, $deviceId);
                    }
                    break;
                case '<=':
                    if ($fieldValue <= $minValue) {
                        $this->saveAlarmRecord($currentTime, $parameter, $fieldValue, $alarmLevel, $deviceId);
                    }
                    break;
                case '=':
                    if ($fieldValue == $minValue) {
                        $this->saveAlarmRecord($currentTime, $parameter, $fieldValue, $alarmLevel, $deviceId);
                    }
                    break;
                case '>=':
                    if ($fieldValue >= $minValue) {
                        $this->saveAlarmRecord($currentTime, $parameter, $fieldValue, $alarmLevel, $deviceId);
                    }
                    break;
                case '<>':
                    if ($minValue != null && $maxValue != null && $fieldValue > $minValue && $fieldValue < $maxValue) {
                        $this->saveAlarmRecord($currentTime, $parameter, $fieldValue, $alarmLevel, $deviceId);
                    }
                    break;
            }

        }
    }

    // 存储报警记录
    private function saveAlarmRecord($time, $parameter, $value, $alarmLevel, $deviceId)
    {
        $alarmRecord = new AlarmLog();
        $alarmRecord->create_time = strtotime($time);
        $alarmRecord->param = $parameter;
        $alarmRecord->value = $value;
        $alarmRecord->alarm_level = $alarmLevel;
        $alarmRecord->device_id = $deviceId;
        $alarmRecord->status = 1;
        $alarmRecord->save();
    }

}
